#ifndef SYM_TABLE_H
#define SYM_TABLE_H

#include "hash.h"
#include "list.h"
#include "symbol.h"

#define SYMBOL_TYPE_VAR  1
#define SYMBOL_TYPE_FUN  2
#define FUN_PARA_LIST_FORMAT_WITH_NAME 1
#define FUN_PARA_LIST_FORMAT_NO_NAME   2
// 具体大小需要测试 TODO
#define VAR_TAB_BIT   5
#define FUN_TAB_BIT   5
#define STR_TAB_BIT   5

#define IS_LOCAL(x)  (x->scope_path.path_len > 1)
#define IS_GLOBAL(x)  (x->scope_path.path_len == 1)
typedef struct scope_info {
	int scope_id;// 初始化为 0，每进入一个大括号，增加 1
	struct list_head head;
	int list_len;
}scope_info_t;

typedef struct scope_node{ // 函数和符号表都用这个结构
	struct list_head entry;
	int id; 
}scope_node_t;

typedef struct sym_table{

	DECLARE_HASHTABLE(var_tab, VAR_TAB_BIT);
	DECLARE_HASHTABLE(fun_tab, FUN_TAB_BIT);
	DECLARE_HASHTABLE(str_tab, STR_TAB_BIT);

	int var_num; // 统计变量个数
	int fun_num; // 统计函数个数
	int str_num; // 统计常量字符串个数
	int literal_num; // 统计常量(整形或者字符)个数

	// 特殊变量
	var_t *void_var;
	var_t *zero;
	var_t *one;
	var_t *four;

	struct list_head var_tab_head; // 记录添加顺序
	scope_info_t scope;
	fun_t *cur_fun; // 当前分析的函数
	int glb_var_num; // 全局变量的个数
}sym_table_t;

extern sym_table_t sym_tab_g;
extern struct list_head glb_vars_head;
void scope_enter(void);
void scope_leave(void);
int sym_table_init(void);
void sym_table_destroy(void);
void add_var(var_t *var);
void add_literal(var_t *literal);
void add_str(var_t *var);
void print_vars_in_addition_order(void);
void show_var(var_t *var, int recursion);
void print_strings(void);
void print_funs(void);
void var_tab_destroy(void);
void fun_tab_destroy(void);
void str_tab_destroy(void);
void print_fun_para_list(fun_t *fun, int format);
void print_scope_path(scope_path_t *scope_path);
void get_cur_scope(scope_path_t *scope_path, int symbol_type);
void def_fun(fun_t *fun);
void decl_fun(fun_t *fun);
fun_t *get_fun(const char *name);
var_t *get_var(const char *name);
sym_info_t get_var_or_fun(const char *name);  
void print_vars_in_table(void);
unsigned int my_hash(const char *name) ;
void show_fun(fun_t *fun);
bool array_is_initialized(var_t *arr);
void print_glb_vars(void);
int get_all_glb_vars(void);
#endif